package com.zxlspace.thread;

public class SynDemo02 {

    public static void main(String[] args) {
        //在单线程模式下，单例模式保证了每个类只有一个实例
       /* Jvm jvm1 = Jvm.getInstance(100);
        Jvm jvm2 = Jvm.getInstance(500);
        System.out.println(jvm1);
        System.out.println(jvm2);*/

        //多线程模式下，单例模式无法保证只有一个实例，加上synchronized 可以保证单例
        JvmThread thread1 = new JvmThread(100);
        JvmThread thread2 = new JvmThread(500);

        thread1.start();
        thread2.start();
    }
}

class JvmThread extends Thread {
    private long time;

    public JvmThread() {

    }

    public JvmThread(long time) {
        this.time = time;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "---->创建" + Jvm.getInstance(time));
    }
}

/***
 * 单例模式（懒汉式）
 * 确保一个类只有一个对象
 * 1. 构造器私有化，避免外部直接创建
 * 2. 声明一个私有的静态变量
 * 3. 创建一个对外的公共的静态方法访问该变量，如果该变量没有对象，创建该对象
 */
class Jvm {
    //声明一个私有的静态变量
    private static Jvm instance = null;

    //构造器私有化，避免外部直接创建
    private Jvm() {

    }

    //创建一个对外的公共的静态方法访问该变量，如果该变量没有对象，创建该对象
    public static Jvm getInstance(long time) {
        //c d e ---->效率 提高 已经存在对象的访问效率
        if (null == instance) {  //double checking 双重检查
            synchronized (Jvm.class) {
                if (null == instance) {
                    try {
                        Thread.sleep(time); //延时 放大错误概率
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    instance = new Jvm();
                }
            }
        }
        return instance;
    }


    //同步块
    public static Jvm getInstance3(long time) {
        //a b c d e 多个线程进入----》效率不高，即使存在对象也需要等待
       synchronized (Jvm.class) {
           if (null == instance) {
               try {
                   Thread.sleep(time); //延时 放大错误概率
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }

               instance = new Jvm();
           }
       }
        return instance;
    }

    //同步方法
    public static synchronized Jvm getInstance2(long time) {
        if (null == instance) {
            try {
                Thread.sleep(time); //延时 放大错误概率
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            instance = new Jvm();
        }
        return instance;
    }

    public static Jvm getInstance1(long time) {
        if (null == instance) {
            try {
                Thread.sleep(time); //延时 放大错误概率
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            instance = new Jvm();
        }
        return instance;
    }
}
